//  nb++, a nuts-and-bolts C++ toolkit.
//  Copyright (C) 1999 Benjamin Geer, Eduardo J. Blanco

#ifndef _NBPP_EXCEPTION
#define _NBPP_EXCEPTION

#include <nb++/osdep.hpp>

#include <exception>
#include <string>

namespace nbpp
{
    using std::string;
    using std::exception;

    /**
     * A base class for exceptions.
     */
    class Exception : public std::exception
    {
    public:
        /**
         * Constructs an Exception with an optional detail message.
         *
         * @param message a detail message indicating the reason for the
         * exception.
         */
        explicit Exception(const string& message = "");

        /**
         * Destructor.
         */
        virtual ~Exception() throw();

        /**
         * @return the exception's class name.
         */
        virtual string getName() const;

        /**
         * @return a detail message indicating the reason for the
         * exception.
         */
        virtual string getMessage() const;

        /**
         * A concatenation of the exception's class name and its detail
         * message, if available.
         */
        string toString( void ) const;

		/**
		   Return only the message, but following the normal C++ notation !

		   @return a ziro terminated const char string 
		 */
		const char *what( void ) const throw();
    protected:
        string m_message;
    };


    /**
     * Indicates that an assertion failed.
     */
    class AssertException : public Exception
    {
    public:
        explicit AssertException(const string& message = "");

        virtual string getName() const;
    };


    /**
     * Indicates that an unexpected exception was thrown.
     *
     * @see ExceptionGuard
     */
    class UnexpectedException : public AssertException
    {
    public:
        explicit UnexpectedException(const string& message = "");

        virtual string getName() const;
    };


    /**
       Indicates that an I/O error has occurred.
     */
    class IOException : public Exception
    {
    public:
        explicit IOException( const string& message = "" ) throw();
		explicit IOException( int ERRNUM, const string& message = "" ) throw();
		~IOException() throw(){}

        virtual string getName() const;

        /**
           Returns the errno from the source of the given exception.

           The definitions of the values can be found in the "errno.h" 
           header file.

           @return errno the error generated by the source of the error.
         */
		int getErrno( void ) const { return m_errno;}
	private:
		int m_errno;
    };


    /**
       Indicates that the IP address of a host could not be resolved.

       The errors are defined in the "netdb.h" include file.
     */
    class UnknownHostException : public IOException
    {
    public:
        explicit UnknownHostException( const string& message = "" ) throw() : 
            IOException( message ) {}
        explicit UnknownHostException( int ERRNUM, const string& message = "" ) throw() : 
            IOException( ERRNUM, message ) {}

        virtual string getName() const;
    };


    /**
     * Indicates that an operation has timed out.
     */
    class TimeoutException : public IOException
    {
    public:
        explicit TimeoutException( const string& message = "" ) throw() :
            IOException( message ) {}
        explicit TimeoutException( int ERRNUM, const string& message = "" ) throw() :
            IOException( ERRNUM, message ) {}

        virtual string getName() const;
    };


    /**
     * Indicates that an error occurred while performing an operation
     * on a socket.
     */
    class SocketException : public IOException
    {
    public:
        explicit SocketException( const string& message = "" ) throw() :
            IOException( message ) {}
		explicit SocketException( int ERRNUM, const string& message = "" ) throw() :
            IOException( ERRNUM, message ) {}

        virtual string getName() const;
    };


    /**
     * Indicates that an error occurred while attempting to bind a
     * socket to a local address and port.
     */
    class BindException : public SocketException
    {
    public:
        explicit BindException( const string& message = "" ) throw() : 
            SocketException( message ) {}
		explicit BindException( int ERRNUM, const string &message = "" ) throw() : 
            SocketException( ERRNUM, message ) {}

        virtual string getName() const;
    };


    /**
     * Indicates that an error occurred while attempting to connect a
     * socket to a remote address and port.
     */
    class ConnectException : public SocketException
    {
    public:
        explicit ConnectException(const string& message = "") throw() :
            SocketException( message ) { }
		explicit ConnectException( int ERRNUM, const string &message = "" ) throw() :
            SocketException( ERRNUM, message ) {}

        virtual string getName() const;
    };


    /**
     * Indicates that the regular expression engine returned an error.
     */
    class RegexException : public Exception
    {
    public:
        explicit RegexException(const string& message = "");

        virtual string getName() const;
    };

    /**
     * Indicates that the element does not exist.
     */
    class NoSuchElementException : public Exception
    {
    public:
        explicit NoSuchElementException(const string& message = "");

        virtual string getName() const;
    };

    /**
     * Indicates that the operation is not supported by the library/OS.
     */
    class UnsupportedOperationException : public Exception
    {
    public:
        explicit UnsupportedOperationException(const string& message = "");

        virtual string getName() const;
    };


    /**
     * Indicates that an error was found while parsing text.
     */
    class ParseException : public Exception
    {
    public:
        explicit ParseException(const string& message = "");

        virtual string getName() const;
    };


    /**
     * Indicates that an error occurred while trying to control
     * a thread or process.
     */
    class ThreadControlException : public Exception
    {
    public:
        explicit ThreadControlException(const string& message = "");

        virtual string getName() const;
    };

	/**
	   This indicate an error occurred while using refcounting.
	 */
	class RefCountException : public Exception
    {
    public:
        explicit RefCountException(const string& message = "");

        virtual string getName() const;
    };
	
}

#endif /* _NBPP_EXCEPTION */
